﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using NPOI.SS.UserModel;

namespace HYCodeBase.ExcelUtility.ExcelORM
{
	internal class TypePropertyInfo
	{
		internal TypePropertyInfo(PropertyInfo inputPropertyInfo, PropertyAttribute inputPropertyAttribute)
		{
			this.m_usePropertyInfo = inputPropertyInfo;
			this.m_usePropertyAttribute = inputPropertyAttribute;
			this.m_useProperType = this.m_usePropertyInfo.PropertyType;
			this.m_bUseLastValueWhenWhiteSpace = this.m_usePropertyAttribute.UseLastValueWhenNull;
			this.m_bChangeToNextRowWhenReadValue = this.m_usePropertyAttribute.ChangeToNextRowWhenReadValue;
			this.IfIsLstType = TypePropertyInfo.CheckLstTypeProperty(this.m_useProperType);
		}

		internal int UseColumnIndex
		{
			get
			{
				return this.m_useColumnIndex;
			}
			private set
			{
				this.m_useColumnIndex = value;
			}
		}

		internal bool UseLastValueWhenWhiteSpace
		{
			get
			{
				return this.m_bUseLastValueWhenWhiteSpace;
			}
			private set
			{
				this.m_bUseLastValueWhenWhiteSpace = value;
			}
		}

		internal bool IfIsLstType
		{
			get
			{
				return this.m_bIfIsLstType;
			}
			private set
			{
				this.m_bIfIsLstType = value;
			}
		}

		internal bool ChangeToNextRowWhenReadValue
		{
			get
			{
				return this.m_bChangeToNextRowWhenReadValue;
			}
			private set
			{
				this.m_bChangeToNextRowWhenReadValue = value;
			}
		}

		internal static bool CheckProperty(PropertyInfo inputPropertyInfo)
		{
			Type propertyType = inputPropertyInfo.PropertyType;
			return TypePropertyInfo.IfTypeCanUse(propertyType) || TypePropertyInfo.CheckLstTypeProperty(propertyType);
		}

		internal void PrepareDataForWrite(IRow inputRow, ref int nowColumnIndex, ref HashSet<int> usedColumnIndex)
		{
			if (0 <= this.m_usePropertyAttribute.UseColumnIndex && !usedColumnIndex.Contains(this.m_usePropertyAttribute.UseColumnIndex))
			{
				this.m_useColumnIndex = this.m_usePropertyAttribute.UseColumnIndex;
			}
			else
			{
				if (!usedColumnIndex.Contains(nowColumnIndex))
				{
					this.m_useColumnIndex = nowColumnIndex;
				}
				else
				{
					while (usedColumnIndex.Contains(nowColumnIndex))
					{
						nowColumnIndex++;
					}
				}
				nowColumnIndex++;
			}
			if (!string.IsNullOrWhiteSpace(this.m_usePropertyAttribute.UseColumnName))
			{
				inputRow.CreateCell(this.m_useColumnIndex).SetCellValue(this.m_usePropertyAttribute.UseColumnName);
			}
		}

		internal void PrepareDataForRead(ISheet inputSheet, out int headerRowIndex)
		{
			headerRowIndex = 0;
			if (0 <= this.m_usePropertyAttribute.UseColumnIndex)
			{
				this.m_useColumnIndex = this.m_usePropertyAttribute.UseColumnIndex;
				return;
			}
			int lastRowNum = inputSheet.LastRowNum;
			for (int i = 0; i <= lastRowNum; i++)
			{
				IRow row = inputSheet.GetRow(i);
				for (int j = 0; j <= (int)row.LastCellNum; j++)
				{
					ICell cell = row.GetCell(j);
					if (cell != null && cell.ToString().Equals(this.m_usePropertyAttribute.UseColumnName))
					{
						this.m_useColumnIndex = j;
						headerRowIndex = i + 1;
						return;
					}
				}
			}
		}

		internal void SetValue(object inputObject, string inputValue)
		{
			if (!this.IfIsLstType)
			{
				this.SetSingleValue(inputObject, inputValue);
				return;
			}
			this.SetLstValue(inputObject, inputValue);
		}

		internal List<string> GetValue(object inputObject)
		{
			List<string> list = new List<string>();
			if (!this.IfIsLstType)
			{
				object value = this.m_usePropertyInfo.GetValue(inputObject);
				if (value != null)
				{
					string item = value.ToString();
					list.Add(item);
				}
			}
			else
			{
				IList list2 = this.m_usePropertyInfo.GetValue(inputObject) as IList;
				if (list2 != null)
				{
					foreach (object obj in list2)
					{
						if (obj != null)
						{
							list.Add(obj.ToString());
						}
					}
				}
			}
			return list;
		}

		private ChageValueDelegate ValueTransformer
		{
			get
			{
				return this.m_usePropertyAttribute.UseTransformer;
			}
		}

		private void SetLstValue(object inputObject, string inputValue)
		{
			object obj = this.m_usePropertyInfo.GetValue(inputObject);
			if (obj == null)
			{
				obj = Activator.CreateInstance(this.m_useProperType);
				this.m_usePropertyInfo.SetValue(inputObject, obj);
			}
			IList list = obj as IList;
			Type type = this.m_useProperType.GetGenericArguments()[0];
			if (this.ValueTransformer != null)
			{
				list.Add(this.ValueTransformer(inputValue));
				return;
			}
			if (type == TypePropertyInfo.m_useStringType)
			{
				list.Add(inputValue);
				return;
			}
			object value = this.ChangeValue(inputValue, type);
			list.Add(value);
		}

		private void SetSingleValue(object inputObject, string inputValue)
		{
			if (this.ValueTransformer != null)
			{
				this.m_usePropertyInfo.SetValue(inputObject, this.ValueTransformer(inputValue));
				return;
			}
			if (this.m_useProperType == TypePropertyInfo.m_useStringType)
			{
				this.m_usePropertyInfo.SetValue(inputObject, inputValue);
				return;
			}
			object value = this.ChangeValue(inputValue, this.m_useProperType);
			this.m_usePropertyInfo.SetValue(inputObject, value);
		}

		private object ChangeValue(string inputValue, Type inputType)
		{
			if (null == this.m_useProperTypeParseMethod)
			{
				this.m_useProperTypeParseMethod = inputType.GetMethod("Parse", new Type[]
				{
					TypePropertyInfo.m_useStringType
				});
			}
			return this.m_useProperTypeParseMethod.Invoke(null, new object[]
			{
				inputValue
			});
		}

		private static bool IfTypeCanUse(Type propertyType)
		{
			return TypePropertyInfo.m_useStringType == propertyType || TypePropertyInfo.IfTypeCanParse(propertyType);
		}

		private static bool IfTypeCanParse(Type propertyType)
		{
			return null != propertyType.GetMethod("Parse", new Type[]
			{
				TypePropertyInfo.m_useStringType
			});
		}

		private static bool CheckLstTypeProperty(Type inputPropertyType)
		{
			return inputPropertyType.IsGenericType && inputPropertyType.GetGenericTypeDefinition() == TypePropertyInfo.m_useListType && TypePropertyInfo.IfTypeCanUse(inputPropertyType.GetGenericArguments()[0]);
		}

		private PropertyInfo m_usePropertyInfo;

		private PropertyAttribute m_usePropertyAttribute;

		private Type m_useProperType;

		private MethodInfo m_useProperTypeParseMethod;

		private MethodInfo m_useProperTypeAddMethod;

		private int m_useColumnIndex;

		private bool m_bUseLastValueWhenWhiteSpace;

		private bool m_bChangeToNextRowWhenReadValue;

		private bool m_bIfIsLstType;

		private static Type m_useStringType = typeof(string);

		private static Type m_useListType = typeof(List<>);

		private const string m_useParseMethodName = "Parse";
	}
}
